# -*- coding:utf-8 -*-

# @Time    : 2023/12/13 07:05
# @Author  : yaodong
# @Email   : yaodong@lingxi.ai
# @File    : QWMsgCallBackProcess.py
# @Software: LLM_internal
# 用于处理企微渠道消息相关的服务
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

import asyncio
import os
import time
import traceback
import json
import uuid

import aiohttp

from bot.insurance_planner_gpt import company_config
from bot.insurance_planner_gpt.agent.split_output_agent import SplitOutputAgent
from bot.insurance_planner_gpt.qw_server.access_token_manager import token_manager
from bot.insurance_planner_gpt.qw_server.common import wework_constants
from bot.insurance_planner_gpt.context_local_util import context_data
from bot.insurance_planner_gpt.qw_server.qw_process.qw_process_contact import QWContactCallBackProcess
from bot.insurance_planner_gpt.utils import date_util
from bot.insurance_planner_gpt.utils.planner_msg_buffer_util import planner_msg_buffer_util
from bot.insurance_planner_gpt.utils.seat_planner_msg_channel import SeatPlannerMsgChannel
from common import constants
from common.log import logger
from bot.insurance_planner_gpt.planner import PlannerGPT

from common.message import ConversationMessage
from db.mysql.entity_service import EntitiesDao
from db.redis.redis_service import RedisMemory
from util_tool.conversation_util import ConversationUtil
from datetime import datetime

redis_memory = RedisMemory()
cu = ConversationUtil()
entities_dao = EntitiesDao()


def get_loops():
    new_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(new_loop)
    return asyncio.get_event_loop()


loop = get_loops()


class QwProcessSeatChannel(SeatPlannerMsgChannel):

    def __init__(self):
        super().__init__()

    async def handle_seat_channel_data(self):
        """
        规划师服务订阅redis队列下的seat_channel 接收坐席转发的消息
        """
        pubsub = self.aio_redis.pubsub()
        await pubsub.subscribe(self.seat_channel)
        try:
            async for ori_message in pubsub.listen():
                if ori_message['type'] == 'message':
                    message = ori_message['data'].decode('utf-8')
                    context_message_all = ConversationMessage.from_json(message)
                    user_session_id = context_message_all.session_id
                    messages = context_message_all.messages
                    # 初始化时客户端发送的消息
                    last_message = messages[-1]
                    message_id = last_message.get('message_id', str(uuid.uuid4()).replace('-', ''))
                    message_id_process = redis_memory.hget("planner_channel:message_id", message_id)
                    if not message_id_process:
                        redis_memory.hset("planner_channel:message_id", message_id, 1)
                        redis_memory.expireat("planner_channel:message_id", date_util.get_next_day_start())
                        last_content_data = last_message['content'][0].data
                        logger.info(
                            f"会话id:{user_session_id},从{self.seat_channel}中获取到一条用户消息:{context_message_all.to_json()}")
                        await self.send_from_session_id(user_session_id, last_content_data)
        except Exception as e:
            logger.error(f"处理{self.seat_channel}通道道消息异常: {str(e)}")
        finally:
            await pubsub.close()
            await pubsub.unsubscribe(self.seat_channel)

    async def send_from_session_id(self, session_id, result):
        if session_id:
            planner_wework_id = session_id.split(":")[0]
            user_id = session_id.split(":")[1]
            if len(result) > 100:
                splitOutputAgent = SplitOutputAgent(result)
                result = await splitOutputAgent.achat_auto_llm(type="gpt")
            # 发送规划师响应给用户
            result_list = result.split('\n\n')
            for result_split in result_list:
                if result_split:
                    await send_msg_to_user(planner_wework_id, user_id, result_split)
                    await asyncio.sleep(5)
            logger.info(f"当前会话:[{session_id}]，响应用户内容为{str(result_list)}")


class QWMsgCallBackProcess:

    def __init__(self, company_id, event_type, robot_id, req_id, message) -> None:
        self.event_type = event_type
        self.robot_id = robot_id
        self.req_id = req_id
        self.company_id = company_id
        self.seat_channel = QwProcessSeatChannel()
        self.message_data = message.get("data", {})

    async def process_all_event_type(self):
        if wework_constants.WEWORK_EVENT_TYPE_RECEIVE_CONTACT_MSG == self.event_type:
            if self.company_id in [2252, '2252']:
                await self.process_receive_msg_2252()
            else:
                await self.process_receive_msg()
        elif wework_constants.WEWORK_EVENT_TYPE_SEND_CONTACT_MSG == self.event_type:
            await self.process_send_msg_success()
        elif wework_constants.WEWORK_EVENT_TYPE_DOWNLOAD_CHAT_FILE == self.event_type:
            await self.download_msg_file()
        elif wework_constants.WEWORK_EVENT_TYPE_TRANCE_VOICE == self.event_type:
            await self.translate_voice()

    async def process_receive_msg_2252(self):
        try:
            receive_time = self.message_data.get('receive_time', '')

            msgDict = self.message_data.get('msg')
            sender_type = msgDict.get('sender_type')
            sender_id = msgDict.get('sender_id', '')
            receiver_id = msgDict.get('receiver_id', '')
            msg_type = msgDict.get('msg_type')
            msg_content = msgDict.get('msg_content')
            msg_id = msgDict.get('msg_id', '')

            msg_content_val = msg_content.get(wework_constants.MSG_TYPE_KEYS.get(str(msg_type)))
            if receiver_id in wework_constants.IDS_EXCLUDE or sender_id in wework_constants.IDS_EXCLUDE:
                logger.info('排除测试用户')
                return

            continue_val = False
            for msg_exclude in wework_constants.MSG_EXCLUDE:
                if msg_exclude in str(msg_content_val):
                    logger.info('排除非有效消息')
                    continue_val = True
                    break
            if continue_val:
                return

            d_dict = {}
            d_dict['sender_id'] = sender_id
            d_dict['receiver_id'] = receiver_id
            d_dict['sender_type'] = sender_type
            d_dict['receive_time'] = receive_time
            d_dict['msg_id'] = msg_id
            d_dict['robot_id'] = self.robot_id
            if receive_time:
                d_dict['receive_time'] = datetime.fromtimestamp(receive_time)
            else:
                d_dict['receive_time'] = datetime.now()

            d_dict['msg_type'] = wework_constants.MSG_TYPE_KEYS.get(str(msg_type))
            d_dict['msg_content'] = msg_content_val

            loop.run_in_executor(None, entities_dao.insert_ql_contact_msg, d_dict)
        except Exception as ee:
            logger.error(traceback.format_exc())

    async def process_receive_msg(self):
        msg = self.message_data.get("msg", {})
        receive_time = self.message_data.get("receive_time")
        msg_content = msg.get("msg_content", {})
        msg_type = msg.get("msg_type")
        msg_id = msg.get("msg_id", "")
        sender_id = msg.get("sender_id", "")
        receiver_id = msg.get("receiver_id", "")
        session_id = receiver_id + ":" + sender_id
        # 处理多个消息类型
        text_content = await self.process_msg_type(msg_content, msg_type, msg_id)

        if not text_content:
            return

            # 不是用户发的暂时不处理
        if sender_id and self.robot_id == sender_id:
            session_id = sender_id + ":" + receiver_id
            # 保存人工直接在圈量后台或手机端发送的消息
            loop.run_in_executor(None, cu.store_conversation_index, session_id,
                                 "agent_" + str(uuid.uuid4()).replace("-", ""),
                                 constants.MESSAGE_TYPE_TEXT, text_content,
                                 constants.ROLE_ASSISTANT, wework_constants.QW_CLIENT_TYPE_DEFAULT)
            return

        # 查询当前是否被处理了 多次回调的处理
        status = redis_memory.get(
            wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "dialogues_process:" + session_id + ":" + msg_id)
        if status:
            return

        redis_memory.sadd('active_sessions:qw', session_id)
        redis_memory.expireat('active_sessions:qw', date_util.get_next_day_start())

        redis_memory.set(
            wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "dialogues_process:" + session_id + ":" + msg_id,
            "1", ex=3600 * 3)
        try:
            # 开启和坐席平台的通道
            asyncio.create_task(self.seat_channel.handle_seat_channel_data())
            # 给所有正在连接的坐席发送用户最新的对话 改为丢到队列
            msg = ConversationMessage.gen_msg(wework_constants.msg_type_dict.get(msg_type), session_id,
                                              wework_constants.QW_CLIENT_TYPE_DEFAULT,
                                              text_content,
                                              session_id, role=constants.ROLE_USER,
                                              message_id=str(uuid.uuid4()).replace("-", ""))
            await self.seat_channel.publish_msg(self.seat_channel.planner_channel, msg)
        except Exception:
            logger.info(f"当前会话id:{session_id},给所有正在连接的坐席发送用户最新的对话异常,{traceback.format_exc()}")

        # 如果缓冲队列里面有消息堆积，就停止之前的协程，然后重新处理"堆积消息+新消息"
        text_content = planner_msg_buffer_util.join_msg2buffer(text_content, session_id)

        logger.info(f"会话id:[{session_id}],获取到用户新的对话:{text_content}")

        # 如果没有消息堆积，那么就把消息放到缓冲队列
        planner_msg_buffer_util.push_msg2buffer(session_id, text_content)

        # 清空记忆
        await self.clear_qw_memory(session_id, text_content)

        # 获取规划师的响应
        try:
            dt_object = datetime.fromtimestamp(receive_time)
            # 将datetime对象格式化成所需的字符串
            user_message_time = dt_object.strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3]
            new_dialogue = {"msg_time": user_message_time, "content": text_content,
                            "msg_type": wework_constants.msg_type_dict.get(msg_type),
                            "role": "user", "msg_id": msg_id}

            result = await self.process_planner(new_dialogue, session_id, sender_id)

            # 如果最新的消息和正在处理的消息不一样就丢弃本次处理
            buffer = planner_msg_buffer_util.get_top_from_buffer(session_id)
            if buffer:
                if buffer.get('msg') != text_content:
                    logger.info(f"当前会话:[{session_id}]  当前处理的消息和缓冲区的消息不一致, 放弃处理该消息")
                    return

            # 处理完成检查一下缓冲队列，如果自己处理的消息和缓冲队列里面拿出来的消息不一致，就不返回；否则把缓冲队列清空
            if not planner_msg_buffer_util.judge_stop_process(text_content, session_id):
                # 存储用户最新的对话
                loop.run_in_executor(None, cu.store_conversation_index,
                                     session_id, msg_id,
                                     wework_constants.msg_type_dict.get(msg_type), text_content,
                                     constants.ROLE_USER,
                                     wework_constants.QW_CLIENT_TYPE_DEFAULT, user_message_time)
                message_id = str(uuid.uuid4()).replace('-', '')
                try:
                    # 发送给坐席平台
                    msg = ConversationMessage.gen_msg(constants.MESSAGE_TYPE_EDIT_TEXT, session_id,
                                                      wework_constants.QW_CLIENT_TYPE_DEFAULT,
                                                      result,
                                                      session_id, role=constants.ROLE_ASSISTANT,
                                                      message_id=message_id,
                                                      action="takeover_response")
                    await self.seat_channel.publish_msg(self.seat_channel.planner_channel, msg)
                except Exception:
                    logger.info(
                        f"当前会话id:{session_id},给所有正在连接的坐席发送用户最新的对话异常,{traceback.format_exc()}")
                await self.human_customer_process(message_id, receiver_id, result, sender_id, session_id, text_content)
        except Exception:
            logger.info(f"会话id:[{session_id}],调用规划师服务异常,{traceback.format_exc()}")
            redis_memory.delete(
                wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "dialogues_process:" + session_id + ":" + msg_id)

    async def human_customer_process(self, message_id, receiver_id, result, sender_id, session_id, text_content):
        try:
            # 判断是否需要人工小助参与
            need_human_customer_service = redis_memory.get(
                wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "need_human_customer_service:" + str(self.company_id))
            # 不需要参与
            if not need_human_customer_service or need_human_customer_service == '0':
                # 存储大模型的最新对话
                logger.info(f"会话id:{session_id}，正常响应，存储规划师的响应：{result}")
                loop.run_in_executor(None, cu.store_conversation_index, session_id,
                                     "origin_" + message_id,
                                     constants.MESSAGE_TYPE_TEXT, result,
                                     constants.ROLE_ASSISTANT, wework_constants.QW_CLIENT_TYPE_DEFAULT)
                takeover_client_id = redis_memory.get("agent_takeover:" + session_id)
                if not takeover_client_id:
                    if len(result) > 100:
                        splitOutputAgent = SplitOutputAgent(result)
                        result = await splitOutputAgent.achat_auto_llm(type="gpt")
                    # 发送规划师响应给用户
                    result_list = result.split('\n\n')
                    for result_split in result_list:
                        if result_split:
                            await send_msg_to_user(self.company_id, receiver_id, sender_id, result_split)
                            await asyncio.sleep(5)
                    logger.info(f"当前会话:[{session_id}]，响应用户内容为{str(result_list)}")
            # 需要参与
            elif need_human_customer_service == '1' and '我通过了你的联系人验证请求，现在我们可以开始聊天了' != text_content:
                user_info = redis_memory.get(
                    wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "user:" + str(self.company_id) + ":" + sender_id)
                nick_name = ""
                try:
                    if user_info:
                        user_info = json.loads(user_info)
                        nick_name = user_info.get("name", "")
                except Exception:
                    pass
                message = "收到一条用户新消息\n昵称：" + nick_name + "\n用户问题是：\n" + text_content + "\n犀心小助回复：\n" + result \
                          + "\n\n确认无误后前往坐席工作台回复, 地址：https://s2.xunjinet.com.cn/msg-worker/#/chat "
                await sendMessageToWx(message)
        except Exception:
            logger.error("人工小助参与异常" + traceback.format_exc())

    async def process_msg_type(self, msg_content, msg_type, msg_id):
        """处理不同的消息类型"""
        if msg_type and msg_type == 2:
            text_content = msg_content.get("text", {}).get("content", "")
        elif msg_type and msg_type == 6:
            # 处理语音
            # md5_content = msg_content.get("voice", {}).get("url", "")
            # down_load_id = str(uuid.uuid4()).replace("-", "")
            # await get_chat_voice_file(self.company_id, self.robot_id, md5_content, down_load_id)

            # redis_memory.set(wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "download_file_id:" + down_load_id, "",
            #                  ex=3600)

            # 修改处理语音变成试用圈量回调
            text_content = await self.get_voice_text_from_translate(msg_id)
        else:
            text_content = ""
        return text_content

    async def get_voice_text_from_translate(self, msg_id):
        """ 等待圈量回调完后 从redis获取内容"""
        # key = wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "translate_voice_msg:" + msg_id
        # try:
        #     # 使用 asyncio.wait_for 来设置超时
        #     text_content = await asyncio.wait_for(redis_memory.get(key), timeout=60.0)
        #     if text_content is None:
        #         logger.debug(f"未在Redis中找到与消息ID {msg_id} 关联的文本内容。")
        #     return text_content
        # except asyncio.TimeoutError:
        #     logger.debug(f"等待从Redis获取消息ID {msg_id} 的文本内容超时。")
        # except Exception as e:
        #     logger.error(f"从Redis获取消息ID {msg_id} 的文本内容时发生错误：{e}")
        # return None
        start_time = time.time()
        while True:
            text_content = redis_memory.get(
                wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "translate_voice_msg:" + msg_id)
            if text_content:
                break
            # 检查是否过了一分钟
            elapsed_time = time.time() - start_time
            if elapsed_time > 60:
                logger.info("已经过了一分钟，仍未获取到结果，退出循环。")
                break
            # 可以选择添加短暂的延迟，以减轻对系统资源的负担
            await asyncio.sleep(10)
        return text_content

    # @DeprecationWarning
    # async def get_voice_text(self, down_load_id):
    #     start_time = time.time()
    #     while True:
    #         text_content = redis_memory.get(
    #             wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "download_file_id:" + down_load_id)
    #         if text_content:
    #             break
    #         # 检查是否过了一分钟
    #         elapsed_time = time.time() - start_time
    #         if elapsed_time > 60:
    #             logger.info("已经过了一分钟，仍未获取到结果，退出循环。")
    #             break
    #         # 可以选择添加短暂的延迟，以减轻对系统资源的负担
    #         await asyncio.sleep(10)
    #     return text_content

    async def clear_qw_memory(self, session_id, text_content):
        """清空记忆"""
        if text_content and self.judge_clear_conversation_histroy(text_content):
            # 清除会话历史
            redis_memory.delete(wework_constants.PLANNER_REDIS_KEY_PREFIX + "task:" + session_id)
            redis_memory.delete(wework_constants.PLANNER_REDIS_KEY_PREFIX + "solution:" + session_id)
            logger.info(f"会话id:[{session_id}],清空记忆:{text_content}")

    async def process_send_msg_success(self):
        """处理发送消息成功的回调"""
        if (redis_memory.exist_key(
                wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "send_msg_req:" + self.req_id)):
            msg_info = redis_memory.get(
                wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "send_msg_req:" + self.req_id)
            if msg_info:
                # 开始处理后
                msg_info = json.loads(msg_info)
                session_id = self.robot_id + ":" + msg_info.get('receiver_id', '')
                redis_memory.delete(wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "send_msg_req:" + self.req_id)
                logger.info(f"会话id:[{session_id}],给用户发送消息成功")

                # 发送成功后缓存小助对话
                # redis_memory.set(
                #     wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "dialogues_history:" + session_id + ":" + msg_id,
                #     json.dumps({"role": "assistant", "content": msg_info.get('msg'),
                #                 "msg_time": int(time.time()),
                #                 "msg_type": wework_constants.msg_type_dict.get(2),
                #                 "msg_id": msg_id}, ensure_ascii=False), ex=3600 * 24 * 7)
                # # 确认给用户发送成功后 存储助手最新的对话
                # loop.run_in_executor(None, cu.store_conversation_index,
                #                      session_id, msg_id,
                #                      wework_constants.msg_type_dict.get(msg_info.get('msg_type', 2)),
                #                      msg_info.get('msg'), "assistant", "qw_planner")

    async def process_planner(self, new_dialogue, session_id, user_id):
        """ 处理规划师响应"""
        result = ""
        context_data.set({"session_id": session_id, "message_id": 'message_id'})

        # 获取历史对话
        context = cu.get_dialogue_history_by_session_id(session_id)
        context.append(new_dialogue)
        # 调用小助服务
        config = company_config.get_config_from_company_id(self.company_id)
        planner_role = config.get("planner_role", "")
        client_type = config.get("client_type", "")
        company_name = config.get("company_name", "")
        company_business = config.get("company_business", "")
        company_values = config.get("company_values", "")

        planner = PlannerGPT(client_type=client_type, planner_role=planner_role, company_name=company_name,
                             company_business=company_business,
                             company_values=company_values)
        # 暂时没有转惠择顾问的逻辑
        # dialogues_history = ConversationProcessUtil.format_conversation_history(context)
        # 判断是否转人
        # transfer_res = await planner_judge_transfer(dialogues_history)
        # if transfer_res:
        #     transfer_flag = transfer_res.get('transfer_flag', False)
        transfer_flag = False
        if transfer_flag:
            await self.transfer_user2agent(self.robot_id, user_id, new_dialogue.get('content', ''))
        else:
            # 获取历史对话拼接用户最新的对话
            result, other_messages = await planner.async_reply(context, session_id,
                                                               wework_constants.QW_CLIENT_TYPE_DEFAULT)
        return result

    async def transfer_user2agent(self, robot_id, user_id, user_msg):
        agent_id = self.get_transfer_agent(robot_id)
        # 获取坐席详情  头像
        agent_name, agent_avatar = QWContactCallBackProcess.get_contact_info_by_redis(agent_id)
        user_name, user_avatar = QWContactCallBackProcess.get_contact_info_by_redis(user_id)

        # 发送用户的给坐席
        await send_name_card(self.company_id, robot_id, user_id, agent_id, user_name, user_avatar)
        # 给用户发一句话
        await send_msg_to_user(self.company_id, robot_id, user_id,
                               wework_constants.WEWORK_PLANNER_SEND_NAME_CARD_INTRODUCE_MSG)

        # 发送坐席的给用户
        await send_name_card(self.company_id, robot_id, agent_id, user_id, agent_name, agent_avatar)

        # 给顾问发一句话 主要是用户的问题
        await send_msg_to_user(self.company_id, robot_id, agent_id, user_msg)

    async def download_msg_file(self):
        pass

    #     current_path = os.path.abspath(__file__)
    #     file_url = self.message_data.get('file_url', '')
    #     file_name = self.message_data.get('file_name', '')
    #     req_id = self.req_id
    #     use_file_name = "ori_" + file_name
    #     logger.info(f"接收到文件：{use_file_name},文件的地址是：{file_url}")
    #
    #     audio_file_dir = os.path.normpath(os.path.join(current_path, '../../../audio_process/audio_temp/'))
    #     audio_process_dir = os.path.normpath(os.path.join(current_path, '../../../audio_process'))
    #     ori_path = audio_file_dir + "/" + use_file_name
    #     # 文件的本地存储路径
    #     if not os.path.exists(audio_file_dir):
    #         os.makedirs(audio_file_dir)
    #     try:
    #         response = requests.get(file_url)
    #         if response.status_code == 200:
    #             with open(ori_path, 'wb') as file:
    #                 file.write(response.content)
    #             logger.info(f"文件下载成功：{use_file_name}")
    #         else:
    #             logger.info(f"文件下载失败: {response.status_code}")
    #     except requests.exceptions.RequestException as err:
    #         logger.error(f"下载文件异常: {err}")
    #
    #     convert_output_file = audio_file_dir + "/" + use_file_name.replace("silk", "wav")
    #
    #     transfer_output_file = convert_output_file.replace("ori_", "")
    #
    #     converter_shell = f"cd /home/admin/app/silk-v3-decoder-master; sh converter.sh {ori_path} wav"
    #     ffmpeg_shell = f"ffmpeg -i {convert_output_file} -ar 16000 {transfer_output_file}"
    #     logger.info(f"converter_shell:{converter_shell}")
    #     logger.info(f"ffmpeg_shell:{ffmpeg_shell}")
    #     subprocess.run(converter_shell, shell=True)
    #     subprocess.run(ffmpeg_shell, shell=True)
    #
    #     # TODO 删除临时文件  ori_path output_file
    #     audio_text = await send_audio_to_websocket(transfer_output_file)
    #     # 加入对话记录
    #     if audio_text:
    #         redis_memory.set(wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "download_file_id:" + req_id,
    #                          str(audio_text), ex=3600)

    async def translate_voice(self):
        msg_id = self.message_data.get('msg_id', '')
        content = self.message_data.get('content', '')
        # 加入对话记录
        if content:
            redis_memory.set(wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "translate_voice_msg:" + msg_id,
                             content, ex=3600)

    def get_transfer_agent(self, robot_id):
        """ 获取一个合适的顾问承接   机器人和顾问 多对1 对应"""
        return redis_memory.get(
            wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "robot_transfer_agent:" + str(
                self.company_id) + ":" + robot_id)

    def judge_clear_conversation_histroy(self, text):
        if "清空记忆" in text or "清除记忆" in text or "清除历史" in text or "清空历史" in text or "重新开始" in text:
            return True
        else:
            return False


async def send_name_card(company_id, robot_id, share_id, receiver_id, share_name, share_avatar):
    """发送名片"""
    response_json = {}

    req_id = str(uuid.uuid4()).replace("-", "")
    token = ""
    if company_id:
        token = await token_manager.get_access_token_by_company_id(company_id)
    try:
        # 处理params
        payload = {
            "robot_id": robot_id,
            "uniq_sn": req_id,
            "msg": {
                "sender_id": robot_id,
                "receiver_id": receiver_id,
                "msg_id": str(uuid.uuid4()).replace("-", ""),
                "msg_type": 8,
                "msg_content": {
                    "name_card": {
                        "share_id": share_id,
                        "ext_info": {
                            "detail": "",
                            "head_img": share_avatar,
                            "nickname": share_name
                        }
                    }
                }
            }
        }
        headers = {'Content-Type': 'application/json', 'Token': token}
        async with aiohttp.ClientSession() as session:
            async with session.post(wework_constants.WEWORK_INTERFACE_SEND_USER_MSG, json=payload,
                                    headers=headers) as response:
                data = await response.json()
                if response.status == 200 and data.get("errcode") == 0:
                    response_json['message'] = "请求发送成功"
                else:
                    response_json['message'] = data.get("err_msg")
    except Exception as ee:
        logger.error(traceback.format_exc())
        response_json['message'] = "请求异常"
    return response_json


async def send_msg_to_user(company_id, robot_id, contact_uid, msg, msg_type=2):
    """给用户发送消息"""
    response_json = {}
    token = ""
    if company_id:
        token = await token_manager.get_access_token_by_company_id(company_id)
    req_id = str(uuid.uuid4()).replace("-", "")
    try:
        content_key = 'text'
        key = 'content'
        if msg_type == 3:
            key = 'url'
            content_key = 'image'
        # 处理params
        payload = {
            "robot_id": robot_id,
            "uniq_sn": req_id,
            "msg": {
                "sender_id": robot_id,
                "receiver_id": contact_uid,
                "msg_id": str(uuid.uuid4()).replace("-", ""),
                "msg_type": msg_type,
                "msg_content": {
                    content_key: {
                        key: msg,
                    }
                }
            }
        }
        headers = {'Content-Type': 'application/json', 'Token': token}
        async with aiohttp.ClientSession() as session:
            async with session.post(wework_constants.WEWORK_INTERFACE_SEND_USER_MSG, json=payload,
                                    headers=headers) as response:
                data = await response.json()
                if response.status == 200 and data.get("errcode") == 0:
                    redis_memory.set(wework_constants.QW_PLANNER_REDIS_KEY_PREFIX + "send_msg_req:" + req_id,
                                     json.dumps({"msg": msg, "receiver_id": contact_uid, "msg_type": msg_type},
                                                ensure_ascii=False),
                                     ex=24 * 3600)
                    response_json['message'] = "请求发送成功"
                else:
                    response_json['message'] = data.get("err_msg")
    except Exception:
        logger.error(traceback.format_exc())
        response_json['message'] = "请求异常"
    return response_json


# @DeprecationWarning
# async def get_chat_voice_file(company_id, robot_id, file_md5, down_load_id):
#     """获取聊天过程中的语音文件"""
#     response_json = {}
#     token = ""
#     if company_id:
#         token = await token_manager.get_access_token_by_company_id(company_id)
#     try:
#         payload = {
#             "file_md5": file_md5,
#             "robot_id": robot_id,
#             "uniq_sn": down_load_id
#         }
#         headers = {'Content-Type': 'application/json', 'Token': token}
#         async with aiohttp.ClientSession() as session:
#             async with session.post(wework_constants.WEWORK_INTERFACE_DOWN_LOAD_CHAT_FILE, json=payload,
#                                     headers=headers) as response:
#                 data = await response.json()
#                 if response.status == 200 and data.get("errcode") == 0:
#                     response_json['message'] = "请求成功"
#                 else:
#                     response_json['message'] = data.get("err_msg")
#     except Exception:
#         response_json['message'] = "请求异常"
#     return response_json


async def sendMessageToWx(content):
    # 企业微信的机器人API的URL
    wx_url = f'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=d4e98166-a0c1-481a-8f49-37bd761853fb'
    # 构建发送消息的请求的json
    data = {"msgtype": "text", "text": {"content": content, "mentioned_mobile_list": ["@all"]}}
    # 发送请求
    headers = {'Content-Type': 'application/json'}
    async with aiohttp.ClientSession() as session:
        async with session.post(wx_url, json=data, headers=headers) as response:
            data = await response.json()


if __name__ == '__main__':
    current_path = os.path.abspath(__file__)
    # file_url = "https://xunji-1307793115.cos.ap-guangzhou.myqcloud.com/212/cb7b314630e543889d3a1c53555ff05d./octet-stream"
    # file_name = "src_1706082562_bd783ed5170347a81129b2f0e3973317.silk"
    # use_file_name = "ori_" + "src_1706082562_bd783ed5170347a81129b2f0e3973317.silk"
    # logger.info(f"接收到文件：{use_file_name},文件的地址是：{file_url}")
    #
    # audio_file_dir = os.path.normpath(os.path.join(current_path, '../../../audio_process/audio_temp/'))
    # audio_process_dir = os.path.normpath(os.path.join(current_path, '../../../audio_process/'))
    # # 文件的本地存储路径
    # if not os.path.exists(audio_file_dir):
    #     os.makedirs(audio_file_dir)
    # try:
    #     response = requests.get(file_url)
    #     if response.status_code == 200:
    #         with open(audio_file_dir + "/" + use_file_name, 'wb') as file:
    #             file.write(response.content)
    #         print(f"File downloaded successfully to {use_file_name}")
    #     else:
    #         print(f"Error downloading the file. Status code: {response.status_code}")
    # except requests.exceptions.RequestException as err:
    #     logger.error(f"Error occurred while downloading file: {err}")
    #
    # ori_path = audio_file_dir + "/" + use_file_name
    #
    # convert_output_file = audio_file_dir + "/" + use_file_name.replace("silk", "wav")
    #
    # transfer_output_file = convert_output_file.replace("ori_", "")
    #
    # # Convert SILK to WAV
    # converter_shell = f"cd {audio_process_dir}/silk-v3-decoder-master; sh converter.sh {ori_path} wav"
    # ffmpeg_shell = f"ffmpeg -i {convert_output_file} -ar 16000 {transfer_output_file}"
    # print(f"converter_shell:{converter_shell}")
    # print(f"ffmpeg_shell:{ffmpeg_shell}")
    # subprocess.run(converter_shell, shell=True)
    # subprocess.run(ffmpeg_shell, shell=True)
    #
    # # TODO 删除临时文件  ori_path output_file
    # loop.run_in_executor(None, send_audio_to_websocket, transfer_output_file)
